using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.TransportProxy.Interop;

namespace Microsoft.Samples.BizTalk.Adapter.Tcp.Receive
{
    /// <summary>
    ///     This class implements a receive adapter in BizTalk.
    /// </summary>
    /// <author>
    ///     Paul Brown
    /// </author>
    public partial class ReceiveAdapter : IBaseComponent,
                                          IBTTransport,
                                          IPersistPropertyBag,
                                          IBTTransportControl,
                                          IBTTransportConfig,
                                          IAdapter
    {
        #region IBTTransportControl Members

        /// <summary>
        ///     This method is called by the messaging engine to initialize the adapter and pass a reference to its
        ///     private transport proxy.
        /// </summary>
        public void Initialize(IBTTransportProxy transportProxy)
        {
            TraceHelper.WriteEntry(TraceLevel.Info, ResourceConstants.ReceiveAdapterInitializeStart, this.TransportType);

            try
            {
                // Save proxy reference
                this._proxy = transportProxy;

                // Start dispatcher
                this._dispatcher = new Dispatcher(this, this.ThreadIdleTimeout);
                KeyValuePair<Type, int>[] workerThreads = new KeyValuePair<Type, int>[3];
                workerThreads[0] = new KeyValuePair<Type, int>(typeof(BatchWorkerThread), this.MaxBatchWorkerThreads);
                workerThreads[1] = new KeyValuePair<Type, int>(typeof(DuplexWorkerThread), this.MaxDuplexWorkerThreads);
                workerThreads[2] = new KeyValuePair<Type, int>(typeof(TransmitWorkerThread), this.MaxTransmitWorkerThreads);
                this._dispatcher.Start(workerThreads, this.LazyInitializeDispatcher);
            }
            catch (Exception e)
            {
                // Set error info on proxy
                TraceHelper.WriteRawEntry(TraceLevel.Error, e.Message);
                this.TransportProxy.SetErrorInfo(e);
            }
            finally
            {
                TraceHelper.WriteEntry(TraceLevel.Info, ResourceConstants.ReceiveAdapterInitializeComplete, this.TransportType);
            }
        }

        /// <summary>
        ///     This method is called by the messaging engine when the adapter should terminate.  It will
        ///     block until all of the actions have been completed.
        /// </summary>
        public void Terminate()
        {
            TraceHelper.WriteEntry(TraceLevel.Info, ResourceConstants.ReceiveAdapterTerminateStart, this.TransportType);

            try
            {
                // Stop each of the endpoints
                foreach (KeyValuePair<string, ReceiveLocation> kvp in this._endpoints)
                {
                    // Stop endpoint
                    kvp.Value.Stop();
                }

                // Stop dispatcher
                this._dispatcher.Stop();
            }
            catch (Exception e)
            {
                // Set error info on proxy
                TraceHelper.WriteRawEntry(TraceLevel.Error, e.Message);
                this.TransportProxy.SetErrorInfo(e);
            }
            finally
            {
                TraceHelper.WriteEntry(TraceLevel.Info, ResourceConstants.ReceiveAdapterTerminateComplete, this.TransportType);
            }
        }

        #endregion
    }
}
